package com.jtpay.payresulthelper.hook;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.webkit.ValueCallback;

import com.jtpay.payresulthelper.db.AliPayColumn;
import com.jtpay.payresulthelper.db.AliQueryOrderColumn;
import com.jtpay.payresulthelper.enums.ErrorEnum;
import com.jtpay.payresulthelper.model.AliPayOrderList;
import com.jtpay.payresulthelper.model.AliPayQueryModel;
import com.jtpay.payresulthelper.thread.ThreadPoolManager;
import com.jtpay.payresulthelper.util.LogUtil;
import com.jtpay.payresulthelper.util.StringUtil;
import com.jtpay.payresulthelper.util.TimeUtil;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;

import dalvik.system.DexClassLoader;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_AUTO_QUERY_ORDER;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_DETAIL_FAIL_INFO;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_ERROR_INFO;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_MAKE_QR_CODE;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_QUERY_ORDER;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_SET_ALI_ACCOUNT;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_SIMULATE_CLICK_CONTINUE;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_SIMULATE_CLICK_START;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_SIMULATE_CLICK_STOP;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_START_DOT;
import static com.jtpay.payresulthelper.constant.HooKConstant.ACTION_STOP_DOT;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_ACTIVITY_DEVICE_LOCK_ACTIVITY_SHELL;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_COLLECTMONEYRPC;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_CONSULT_SET_AMOUNT_REQ;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_GET_BILL_LIST_DATA_RUNNABLE;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_H5_WEBVIEW;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_PAGING_CONDITION;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_QUERY_LIST_REQ;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_QUERY_LIST_RES;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_RPCSERVICEIMPL;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_SECURITY;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_SERVICE_DAO;
import static com.jtpay.payresulthelper.constant.HooKConstant.CLASS_SINGLE_LIST_ITEM;
import static com.jtpay.payresulthelper.constant.HooKConstant.CONTENT_TASK_URI;
import static com.jtpay.payresulthelper.constant.HooKConstant.CONTENT_TEMP_URI;
import static com.jtpay.payresulthelper.constant.HooKConstant.CONTENT_URI;
import static com.jtpay.payresulthelper.constant.HooKConstant.EXTRA_KEY_ALI_ACCOUNT;
import static com.jtpay.payresulthelper.constant.HooKConstant.EXTRA_KEY_ERROR;
import static com.jtpay.payresulthelper.constant.HooKConstant.EXTRA_KEY_PAY_MODEL;
import static com.jtpay.payresulthelper.constant.HooKConstant.EXTRA_KEY_TEMP_ORDER;
import static com.jtpay.payresulthelper.constant.HooKConstant.SO_FILE_NAME_ALI;
import static com.jtpay.payresulthelper.constant.HooKConstant.WEBVIEW_JS_BILL;


/**
 * new Xposed for alipay
 */
public final class AliPayHook {
    // we need status = 2 for 小买卖
    private static final String CATEGORY_NAME_SMALL_BUSINESS = "小买卖";
    private static final String STATUS_QRCODE = "2";
    private static final String TYPE_CATEGORYID = "06";
    private static final String TYPE_DATE = "day";
    private static final String BIZ_SUB_TYPE_SMALL_BUSINESS = "104";
    // msy type for handler
    //开始模拟点击的消息
    private static final int MSG_TYPE_SIMULATE_CLICK_START = 0;
    //继续模拟点击的消息
    private static final int MSG_TYPE_SIMULATE_CLICK_CONTINUE = 1;
    //结束模拟点击的消息
    private static final int MSG_TYPE_SIMULATE_CLICK_STOP = 2;
    //获取详情的消息
    private static final int MSG_TYPE_GET_DETAIL_FAIL = 3;
    //其它错误的消息
    private static final int MSG_TYPE_ERROR = 4;
    private static final int MSG_TYPE_GET_TRADE_INFO = 5;
    //打点
    private static final int MSG_TYPE_START_DOT = 6;
    //停止打点
    private static final int MSG_TYPE_STOP_DOT = 7;

    //自动补单
    private static final int MSG_TYPE_AUTO_GET_ORDER = 8;

    private static final int TYPE_AUTO_QUERY = 0;
    private static final int TYPE_QUERY = 1;
    private static final long TIME_STAMP_ERROR = -1;

    //时间戳查询
    private static final int TYPE_SERVER_QUERY_TIME_ONLY = 0;
    //备注查询
    private static final int TYPE_SERVER_QUERY_REMARK = 1;
    //订单号查询
    private static final int TYPE_SERVER_QUERY_ORDER = 2;
    //获取订单列表的消息
    protected ContentResolver mContentResolver;
    private int mQueryType;
    private boolean mServerQuery = false;
    private boolean mQuery = false;
    private DexClassLoader mAliPatchClassloader;
    private ExecutorService mExecutorService = ThreadPoolManager.getInstance().getExecutorService();
    private ClassLoader mClassLoader;
    private Activity mActivity;
    private AliPayReceiver mAliPayReceiver = new AliPayReceiver();
    private MsgHandler mHandler;
    private AliPayJavaScriptInterface mAliPayJavaScriptInterface = new AliPayJavaScriptInterface();
    private AliPayServerJavaScriptInterface mAliPayServerJavaScriptInterface = new AliPayServerJavaScriptInterface();
    private Class mH5WebView;
    private Uri mUri = Uri.parse(CONTENT_URI);
    private Uri mTaskUri = Uri.parse(CONTENT_TASK_URI);
    private Uri mTempUri = Uri.parse(CONTENT_TEMP_URI);

    private String mAliAccount;
    //当支付宝加载的时候, 需要从数据库读取当天的内容
    private List<AliPayOrderList> mAliPayAllOrderList = new ArrayList<>();

    //每次获取的新的订单内容
    private List<AliPayOrderList> mAliPayOnceOrderList = new ArrayList<>();

    //服务器抓单列表
    private List<AliPayOrderList> mAliPayServerCheckOrderList = new ArrayList<>();


    private QueryRunnable mOrderRunnable = new QueryRunnable();
    private ServerQueryRunnable mServerOrderRunnable = new ServerQueryRunnable();

    //标明一次通知是否处理完毕
    private int mOrderStatus;
    Object mRpcServiceImpl;
    Object mRpc;
    //从数据库里获取最新的一条数据作为基准数据
    private Runnable mLoadDateOrder = new Runnable() {
        @Override
        public void run() {
            Cursor cursor = mContentResolver.query(mUri, null, AliPayColumn._ACCOUNT + " =? ", new String[]{mAliAccount}, AliPayColumn._TIME_STAMP + " DESC");
            if (null != cursor) {
                while (cursor.moveToNext()) {
                    String money = cursor.getString(cursor.getColumnIndex(AliPayColumn._MONEY));
                    String binInNo = cursor.getString(cursor.getColumnIndex(AliPayColumn._ORDER_NUMBER));
                    String formatTime = cursor.getString(cursor.getColumnIndex(AliPayColumn._TIME_STAMP));
                    AliPayOrderList list = new AliPayOrderList();
                    list.setBizInNo(binInNo);
                    list.setConsumeFee(money);
                    list.setTime(formatTime);
                    mAliPayAllOrderList.add(list);
                    break;
                }
                printAllOrder();
                cursor.close();
            }
            mHandler.sendEmptyMessage(MSG_TYPE_AUTO_GET_ORDER);
        }
    };

    public AliPayHook(ClassLoader classLoader, Activity activity) {
        mOrderStatus = 0;
        mClassLoader = classLoader;
        mHandler = new MsgHandler(Looper.getMainLooper());
        mActivity = activity;
        mContentResolver = mActivity.getContentResolver();
        initReceiver();
        securityCheckHook(mClassLoader);
        initDexClassLoaderAndLoadDex();
        hookH5(mClassLoader);
        hookTradeService();
        initRpcServiceImpl();
        hookDeviceLockActivityShell();
    }

    private void hookDeviceLockActivityShell() {
        Class cls = XposedHelpers.findClass(CLASS_ACTIVITY_DEVICE_LOCK_ACTIVITY_SHELL, mClassLoader);
        XposedHelpers.findAndHookMethod(cls, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
            }
        });
    }

    private void initRpcServiceImpl() {
        try {
            Class cls = XposedHelpers.findClass(CLASS_RPCSERVICEIMPL, mClassLoader);
            mRpcServiceImpl = cls.newInstance();
            Method getRpcProxy = cls.getDeclaredMethod("getRpcProxy", Class.class);
            Class clsRpc = XposedHelpers.findClass(CLASS_COLLECTMONEYRPC, mClassLoader);
            mRpc = getRpcProxy.invoke(mRpcServiceImpl, clsRpc);
        } catch (InstantiationException e) {
            e.printStackTrace();
            LogUtil.log("initRpcServiceImpl InstantiationException");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            LogUtil.log("initRpcServiceImpl IllegalAccessException");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            LogUtil.log("initRpcServiceImpl NoSuchMethodException");
        } catch (InvocationTargetException e) {
            LogUtil.log("initRpcServiceImpl InvocationTargetException");
            e.printStackTrace();
        }
    }

    //从数据库获取最新的时间戳
    private long getNewTimeStampFromDb() {
        long timeStamp = TIME_STAMP_ERROR;
        LogUtil.log("getNewTimeStampFromDb mAliAccount " + mAliAccount);
        Cursor cursor = mContentResolver.query(mUri, null, AliPayColumn._ACCOUNT + " =? ", new String[]{mAliAccount}, AliPayColumn._TIME_STAMP + " DESC");
        LogUtil.log("getNewTimeStampFromDb mAliAccount2 " + mAliAccount);
        if (null != cursor) {
            int size = cursor.getCount();
            LogUtil.log("getNewTimeStampFromDb size = " + size);
            while (cursor.moveToNext()) {
                String time = cursor.getString(cursor.getColumnIndex(AliPayColumn._TIME_STAMP));
                timeStamp = TimeUtil.stringToTimeStamp(time);
                break;
            }
            cursor.close();
        }
        LogUtil.log("getNewTimeStamp timeStamp " + timeStamp);
        return timeStamp;
    }

    // xposed check,为了能够使用Xposed
    private void securityCheckHook(ClassLoader classLoader) {
        Class cls = XposedHelpers.findClass(CLASS_SECURITY, classLoader);
        XposedHelpers.findAndHookMethod(cls, "a", new Object[]{String.class, String.class, String.class, new XC_MethodHook() {
            protected void afterHookedMethod(XC_MethodHook.MethodHookParam arg4) {
                Object v0 = arg4.getResult();
                XposedHelpers.setBooleanField(v0, "a", false);
                arg4.setResult(v0);
            }
        }});
        XposedHelpers.findAndHookMethod(cls, "a", new Object[]{Class.class, String.class, String.class, new XC_MethodReplacement() {
            protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam arg2) {
                return Byte.valueOf((byte) 1);
            }
        }});
        XposedHelpers.findAndHookMethod(cls, "a", new Object[]{ClassLoader.class, String.class, new XC_MethodReplacement() {
            protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam arg2) {
                return Byte.valueOf((byte) 1);
            }
        }});
        XposedHelpers.findAndHookMethod(cls, "a", new Object[]{new XC_MethodReplacement() {
            protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam arg2) {
                return Boolean.valueOf(false);
            }
        }});

    }

    //用来触发订单详情，用来抓订单详情
    private void hookH5(ClassLoader classLoader) {
        mH5WebView = XposedHelpers.findClass(CLASS_H5_WEBVIEW, classLoader);
        XposedHelpers.findAndHookMethod(mH5WebView, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) {
                try {
                    super.afterHookedMethod(param);
                    final Object webview = param.thisObject;
                    if (null != webview && isAliAccountSet()) {
                        mExecutorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                mHandler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        Method evaluateJavascript;
                                        try {
                                            evaluateJavascript = mH5WebView.getDeclaredMethod("evaluateJavascript", String.class, ValueCallback.class);
                                            if (!mServerQuery) {
                                                evaluateJavascript.invoke(webview, WEBVIEW_JS_BILL, mAliPayJavaScriptInterface);
                                            } else {
                                                evaluateJavascript.invoke(webview, WEBVIEW_JS_BILL, mAliPayServerJavaScriptInterface);
                                            }
                                        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                                            e.printStackTrace();
                                            LogUtil.log("H5WebView onResume exception reason " + e.getMessage());
                                            wrapperErrorMsg(ErrorEnum.ERROR_GET_DETAIL.ordinal());
                                        }
                                    }
                                }, 2000L);
                            }
                        });
                    }
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                    LogUtil.log("H5WebView onResume throwable reason " + throwable.getMessage());
                    wrapperErrorMsg(ErrorEnum.ERROR_H5_WEBVIEW.ordinal());
                }
            }
        });
    }

    /**
     * 初始化，为了接收生产程序的主动查单请求
     */
    private void initReceiver() {
        LogUtil.log("initReceiver");
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_QUERY_ORDER);
        intentFilter.addAction(ACTION_MAKE_QR_CODE);
        intentFilter.addAction(ACTION_AUTO_QUERY_ORDER);
        intentFilter.addAction(ACTION_SET_ALI_ACCOUNT);
        mActivity.registerReceiver(mAliPayReceiver, intentFilter);
    }

    //初始化Ali Dex
    private void initDexClassLoaderAndLoadDex() {
        // /data/user/0/com.eg.android.AlipayGphone/ 路径
        String dataDir = mActivity.getFilesDir().getParent();
        File aliLib = new File(dataDir, SO_FILE_NAME_ALI);
        if (aliLib.exists()) {
            String aliLibName = aliLib.getAbsolutePath().toString();
            File dexOutputDir = mActivity.getDir("dex", 0);
            mAliPatchClassloader = new DexClassLoader(aliLibName, dexOutputDir.getAbsolutePath(), null, mActivity.getClassLoader());
        }
    }

    //获取订单，参数参考AliPayQueryModel
    private void getOrder(AliPayQueryModel model) {
        if (null != mExecutorService) {
            mOrderRunnable.setQueryCondition(model.getStartTime(), model.getEndTime(), model.getDateType());
            mExecutorService.execute(mOrderRunnable);
        }
    }

    //服务器获取订单
    private void getServerOrder(long startTime, long endTime, String dataType, String remark, String order, int queryType) {
        if (null != mExecutorService) {
            mServerOrderRunnable.setQueryCondition(startTime, endTime, dataType, remark, order, queryType);
            mExecutorService.execute(mServerOrderRunnable);
        }
    }

    private void printAllOrder() {
        if (0 != mAliPayAllOrderList.size()) {
            for (AliPayOrderList list : mAliPayAllOrderList) {
                LogUtil.log("printAllOrder " + list.toString());
            }
        }
    }

    private void printOnceOrder() {
        if (0 != mAliPayOnceOrderList.size()) {
            for (AliPayOrderList list : mAliPayOnceOrderList) {
                LogUtil.log("printOnceOrder " + list.toString());
            }
        }
    }

    //条件满足的话，作为主动发起交易查询的触发点，查询当前的订单
    private void hookTradeService() {
        XposedBridge.hookAllMethods(XposedHelpers.findClass(CLASS_SERVICE_DAO, mClassLoader), "insertMessageInfo", new XC_MethodHook() {
            protected void beforeHookedMethod(XC_MethodHook.MethodHookParam arg4) {
                try {
                    super.beforeHookedMethod(arg4);
                    String arg0 = getStr(XposedHelpers.callMethod(arg4.args[0], "toString", new Object[0]).toString(), "extraInfo=\'", "\'").replace("\\", "");
                    if ((arg0.contains("收钱到账")) || (arg0.contains("收款到账"))) {
                        LogUtil.log("hookTradeService " + arg0);
                        queryOrderInner();
                    }
                } catch (Throwable throwable) {
                    LogUtil.log("hookTradeService  Throwable " + throwable.getMessage());
                    throwable.printStackTrace();
                }
            }
        });
    }

    /**
     * 发送错误消息
     *
     * @param action ACTION_ERROR_INFO
     * @param type   ErrorEnum
     */
    private void sentIntent(String action, int type) {
        LogUtil.log("sentIntent action " + action + " type " + type);
        Intent intent = new Intent(action);
        intent.putExtra(EXTRA_KEY_ERROR, type);
        mActivity.sendBroadcast(intent);
    }

    //发送正常的消息
    private void sentIntent(String action) {
        LogUtil.log("sentIntent action " + action);
        Intent intent = new Intent(action);
        mActivity.sendBroadcast(intent);
    }

    //包装错误消息
    private void wrapperErrorMsg(int errorType) {
        Message message = Message.obtain();
        message.what = MSG_TYPE_ERROR;
        message.arg1 = errorType;
        mHandler.sendMessage(message);
    }

    //发送服务器查单开始数据
    private void sentSimulateIntent(String action, AliPayQueryModel model) {
        LogUtil.log("sentSimulateIntent action " + action);
        Intent intent = new Intent(action);
        intent.putExtra(EXTRA_KEY_PAY_MODEL, model);
        mActivity.sendBroadcast(intent);
    }

    //发送服务器,continue, stop ,区别正常的消息
    private void sentSimulateOtherIntent(String action, String tableName) {
        LogUtil.log("sentSimulateOtherIntent action " + action);
        Intent intent = new Intent(action);
        intent.putExtra(EXTRA_KEY_TEMP_ORDER, tableName);
        mActivity.sendBroadcast(intent);
    }

    //获取订单消息
    private void wrapperMsg(AliPayQueryModel model) {
        Message message = Message.obtain();
        message.what = MSG_TYPE_GET_TRADE_INFO;
        message.obj = model;
        mHandler.sendMessage(message);
    }

    //服务端主动查询的模拟点击开始
    private void wrapperSimulateStartMsg(AliPayQueryModel model) {
        Message message = Message.obtain();
        message.what = MSG_TYPE_SIMULATE_CLICK_START;
        message.obj = model;
        mHandler.sendMessage(message);
    }

    //服务端主动查询的模拟点击结束
    private void wrapperSimulateStopMsg() {
        Message message = Message.obtain();
        message.what = MSG_TYPE_SIMULATE_CLICK_STOP;
        message.obj = AliPayColumn._TABLE_TEMP_NAME;
        mHandler.sendMessage(message);
    }

    //服务端主动查询的模拟点击继续
    private void wrapperSimulateContinueMsg() {
        Cursor cursor = mContentResolver.query(mTaskUri, null, AliQueryOrderColumn._IS_OK + " =? ", new String[]{"1"}, AliQueryOrderColumn._ID + " ASC");
        if (null != cursor) {
            int size = cursor.getCount();
            LogUtil.log("wrapperSimulateContinueMsg size " + size);
            while (cursor.moveToNext()) {
                long id = cursor.getLong(cursor.getColumnIndex(AliQueryOrderColumn._ID));
                updateTaskDbStatus(id, "2");
                break;
            }
            cursor.close();
        }
        Message message = Message.obtain();
        message.what = MSG_TYPE_SIMULATE_CLICK_CONTINUE;
        message.obj = AliPayColumn._TABLE_TEMP_NAME;
        mHandler.sendMessage(message);
    }

    //解析支付宝订单通知的消息
    private String getStr(String arg2, String arg3, String arg4) {
        String ret;
        try {
            int index = arg2.indexOf(arg3) + arg3.length();
            ret = arg2.substring(index, arg2.indexOf(arg4, index));
        } catch (Exception v0) {
            v0.printStackTrace();
            ret = "error";
        }
        return ret;
    }

    //获取最新的list从数据库中
    private void loadCurrentDateOrder() {
        if (null != mExecutorService) {
            mExecutorService.execute(mLoadDateOrder);
        }
    }

    //内部查询
    private void queryOrderInner() {
        AliPayQueryModel model = new AliPayQueryModel();
        long startTime = getNewTimeStampFromDb();
        if (TIME_STAMP_ERROR == startTime) {
            startTime = TimeUtil.getHalfHourTimeStamp();
        }
        long endTime = TimeUtil.getCurrentTimeStamp();
        LogUtil.log("queryOrderInner startTime = " + startTime + " endTime = " + endTime);
        model.setStartTime(startTime);
        model.setEndTime(endTime);
        model.setDateType(TYPE_DATE);
        wrapperMsg(model);
    }

    class MsgHandler extends Handler {
        public MsgHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int what = msg.what;
            switch (what) {
                case MSG_TYPE_GET_DETAIL_FAIL:
                    sentIntent(ACTION_DETAIL_FAIL_INFO);
                    break;
                case MSG_TYPE_SIMULATE_CLICK_START: {
                    Object object = msg.obj;
                    if (null != object) {
                        AliPayQueryModel model = (AliPayQueryModel) object;
                        sentSimulateIntent(ACTION_SIMULATE_CLICK_START, model);
                    } else {
                        sentIntent(ACTION_SIMULATE_CLICK_START);
                    }
                    break;
                }
                case MSG_TYPE_SIMULATE_CLICK_CONTINUE: {
                    Object object = msg.obj;
                    if (null != object) {
                        String tableName = (String) object;
                        sentSimulateOtherIntent(ACTION_SIMULATE_CLICK_CONTINUE, tableName);
                    } else {
                        sentIntent(ACTION_SIMULATE_CLICK_CONTINUE);
                    }
                    break;
                }
                case MSG_TYPE_SIMULATE_CLICK_STOP: {
                    checkTask();
                    Object object = msg.obj;
                    if (null != object) {
                        String tableName = (String) object;
                        sentSimulateOtherIntent(ACTION_SIMULATE_CLICK_STOP, tableName);
                    } else {
                        sentIntent(ACTION_SIMULATE_CLICK_STOP);
                    }
                    break;
                }
                case MSG_TYPE_ERROR:
                    int arg1 = msg.arg1;
                    sentIntent(ACTION_ERROR_INFO, arg1);
                    break;
                case MSG_TYPE_GET_TRADE_INFO:
                    AliPayQueryModel model = (AliPayQueryModel) msg.obj;
                    mQuery = true;
                    mQueryType = TYPE_QUERY;
                    getOrder(model);
                    break;
                case MSG_TYPE_START_DOT:
                    sentIntent(ACTION_START_DOT);
                    break;
                case MSG_TYPE_STOP_DOT:
                    sentIntent(ACTION_STOP_DOT);
                    break;
                case MSG_TYPE_AUTO_GET_ORDER:
                    autoGetOrder();
                    break;
                default:
                    break;
            }
        }
    }

    //检查任务
    private void checkTask() {
        //first, check server task
        if (mServerQuery) {
            serverCheckDatabase();
        } else if (mQuery) {
            queryOrderInner();
        }
    }

    //自动补单查询
    private void autoGetOrder() {
        LogUtil.log("autoGetOrder");
        long startTime = getNewTimeStampFromDb();
        //如果数据库没有内容，直接通知打点
        if (TIME_STAMP_ERROR == startTime) {
            LogUtil.log("autoGetOrder = " + TIME_STAMP_ERROR);
            mQuery = false;
            mHandler.sendEmptyMessage(MSG_TYPE_START_DOT);
            return;
        }
        long endTime = TimeUtil.getCurrentTimeStamp();
        AliPayQueryModel model = new AliPayQueryModel();
        model.setStartTime(startTime);
        model.setEndTime(endTime);
        model.setDateType(TYPE_DATE);
        getOrder(model);
    }

    //server check order
    private void serverOrderCheck() {
        //if normal querying,later get check order
        LogUtil.log("serverOrderCheck mQuery " + mQuery);
        if (!mQuery) {
            serverCheckDatabase();
        }
    }

    //check task
    private void serverCheckDatabase() {
        LogUtil.log("serverCheckDatabase");
        Cursor cursor = mContentResolver.query(mTaskUri, null, AliQueryOrderColumn._IS_OK + " =? ", new String[]{"0"}, AliQueryOrderColumn._ID + " ASC");
        if (null != cursor) {
            int size = cursor.getCount();
            LogUtil.log("serverCheckDatabase size " + size);
            if (size > 0) {
                while (cursor.moveToNext()) {
                    String stampBegin = cursor.getString(cursor.getColumnIndex(AliQueryOrderColumn._TIME_STAMP_BEGIN));
                    String stampEnd = cursor.getString(cursor.getColumnIndex(AliQueryOrderColumn._TIME_STAMP_END));
                    String remark = cursor.getString(cursor.getColumnIndex(AliQueryOrderColumn._REMARK));
                    String orderNumber = cursor.getString(cursor.getColumnIndex(AliQueryOrderColumn._ORDER_NUMBER));
                    long id = cursor.getLong(cursor.getColumnIndex(AliQueryOrderColumn._ID));
                    int queryType = TYPE_SERVER_QUERY_TIME_ONLY;
                    if (!TextUtils.isEmpty(remark)) {
                        queryType = TYPE_SERVER_QUERY_REMARK;
                    } else if (!TextUtils.isEmpty(orderNumber)) {
                        queryType = TYPE_SERVER_QUERY_ORDER;
                    }
                    LogUtil.log("serverCheckDatabase " + String.format("stampBegin = %s,stampEnd = %s,remark = %s,orderNumber = %s, queryType = %d", stampBegin, stampEnd, remark, orderNumber, queryType));
                    updateTaskDbStatus(id, "1");
                    getServerOrder(Long.valueOf(stampBegin), Long.valueOf(stampEnd), TYPE_DATE, remark, orderNumber, queryType);
                    break;
                }
            } else {
                mServerQuery = false;
            }
            cursor.close();
        } else {
            mServerQuery = false;
        }
    }

    /**
     * @param id      table id
     * @param treated 0 def 1 start  2 done
     */
    private void updateTaskDbStatus(long id, String treated) {
        ContentValues values = new ContentValues();
        Uri updateIdUri = ContentUris.withAppendedId(
                mTaskUri, id);
        values.put(AliQueryOrderColumn._IS_OK, treated);
        mContentResolver.update(updateIdUri, values, null, null);
    }

    //用来接收抓单程序的命令
    class AliPayReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            LogUtil.log("AliPayReceiver action = " + action);
            switch (action) {
                case ACTION_QUERY_ORDER:
                    mServerQuery = true;
                    serverOrderCheck();
                    break;
                case ACTION_MAKE_QR_CODE:
                    makeOrder();
                    break;
                case ACTION_AUTO_QUERY_ORDER:
                    mQueryType = TYPE_AUTO_QUERY;
                    mQuery = true;
                    loadCurrentDateOrder();
                    break;
                case ACTION_SET_ALI_ACCOUNT:
                    String aliAccount = intent.getStringExtra(EXTRA_KEY_ALI_ACCOUNT);
                    setAliAccount(aliAccount);
                    clearPayOrderList();
                    break;
                default:
                    break;
            }
        }
    }

    //生产二维码
    private void makeOrder() {
        if (null != mExecutorService) {
            mExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    if (null != mRpc) {
                        try {
                            Class req = XposedHelpers.findClass(CLASS_CONSULT_SET_AMOUNT_REQ, mClassLoader);
                            Object reqObject = req.newInstance();
                            XposedHelpers.setObjectField(reqObject, "amount", "0.20");
                            XposedHelpers.setObjectField(reqObject, "desc", "12345678987654321");
                            Method consultSetAmountResMethod = mRpc.getClass().getDeclaredMethod("consultSetAmount", req);
                            Object resObject = consultSetAmountResMethod.invoke(mRpc, reqObject);
                            String qrCodeUrl = (String) XposedHelpers.getObjectField(resObject, "qrCodeUrl");
                            String codeId = (String) XposedHelpers.getObjectField(resObject, "codeId");
                            String printQrCodeUrl = (String) XposedHelpers.getObjectField(resObject, "printQrCodeUrl");
                            LogUtil.log("makeOrder " + String.format("qrCodeUrl = %s,codeId = %s, printQrCodeUrl = %s", qrCodeUrl, codeId, printQrCodeUrl));
                        } catch (NoSuchMethodException e) {
                            LogUtil.log("makeOrder NoSuchMethodException " + e.getMessage());
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            LogUtil.log("makeOrder IllegalAccessException " + e.getMessage());
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            LogUtil.log("makeOrder InvocationTargetException " + e.getMessage());
                            e.printStackTrace();
                        } catch (InstantiationException e) {
                            LogUtil.log("makeOrder InstantiationException " + e.getMessage());
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    }

    //服务端主动查询订单
    class ServerQueryRunnable implements Runnable {
        long mStartTime;
        long mEndTime;
        String mDateType;
        String mRemark;
        String mOrder;
        int mQueryType;

        public void setQueryCondition(long startTime, long endTime, String dateType, String remark, String order, int queryType) {
            mStartTime = startTime;
            mEndTime = endTime;
            mDateType = dateType;
            mOrder = order;
            mRemark = remark;
            mQueryType = queryType;
        }

        public long getEndTime() {
            return mEndTime;
        }

        public String getOrder() {
            return mOrder;
        }

        public long getStartTime() {
            return mStartTime;
        }

        public String getRemark() {
            return mRemark;
        }

        public int getQueryType() {
            return mQueryType;
        }

        @Override
        public void run() {
            if (null != mAliPatchClassloader) {
                LogUtil.log("ServerQueryRunnable run");
                mAliPayServerCheckOrderList.clear();
                try {
                    LogUtil.log("startTime " + mStartTime);
                    LogUtil.log("endTime " + mEndTime);
                    Class<?> cls = mClassLoader.loadClass(CLASS_QUERY_LIST_REQ);
                    Object object = cls.newInstance();
                    Field category = cls.getDeclaredField("category");
                    category.setAccessible(true);
                    category.set(object, "ALL");
                    Field pageType = cls.getDeclaredField("pageType");
                    pageType.setAccessible(true);
                    pageType.set(object, "WaitPayConsumeQuery");
                    Field paging = cls.getDeclaredField("paging");
                    paging.setAccessible(true);
                    Class<?> pageConditionCls = mClassLoader.loadClass(CLASS_PAGING_CONDITION);
                    Object objectPageCondition = pageConditionCls.newInstance();
                    paging.set(object, objectPageCondition);
                    Field needMonthSeparator = cls.getDeclaredField("needMonthSeparator");
                    needMonthSeparator.setAccessible(true);
                    needMonthSeparator.set(object, false);

                    Field scene = cls.getDeclaredField("scene");
                    scene.setAccessible(true);
                    scene.set(object, "BILL_LIST");

                    Field startTime = cls.getDeclaredField("startTime");
                    startTime.setAccessible(true);
                    startTime.set(object, mStartTime);

                    Field endTime = cls.getDeclaredField("endTime");
                    endTime.setAccessible(true);
                    endTime.set(object, mEndTime);

                    Field asyncQueryTaskId = cls.getDeclaredField("asyncQueryTaskId");
                    asyncQueryTaskId.setAccessible(true);
                    asyncQueryTaskId.set(object, 0L);

                    Field dateType = cls.getDeclaredField("dateType");
                    dateType.setAccessible(true);
                    dateType.set(object, mDateType);

                    Field bizSubTypeReqField = cls.getDeclaredField("bizSubType");
                    bizSubTypeReqField.setAccessible(true);
                    bizSubTypeReqField.set(object, BIZ_SUB_TYPE_SMALL_BUSINESS);

                    Field categoryId = cls.getDeclaredField("categoryId");
                    categoryId.setAccessible(true);
                    categoryId.set(object, TYPE_CATEGORYID);

                    Class<?> runnableCls = mAliPatchClassloader.loadClass(CLASS_GET_BILL_LIST_DATA_RUNNABLE);
                    Object objectRunnable = runnableCls.newInstance();
                    Method method = runnableCls.getDeclaredMethod("execute", Object[].class);
                    method.setAccessible(true);
                    Object result = method.invoke(objectRunnable, new Object[]{new Object[]{object}});
                    Class queryListResCls = mClassLoader.loadClass(CLASS_QUERY_LIST_RES);
                    Field billListItemsField = queryListResCls.getDeclaredField("billListItems");
                    billListItemsField.setAccessible(true);
                    List queryListRes = (List) billListItemsField.get(result);
                    Class<?> pbCls = mClassLoader.loadClass(CLASS_SINGLE_LIST_ITEM);

                    int size = queryListRes.size();
                    LogUtil.log("ServerQueryRunnable size = " + size);
                    if (size != 0) {
                        for (int i = 0; i < size; i++) {
                            Object res = queryListRes.get(i);

                            Field bizInNoField = pbCls.getDeclaredField("bizInNo");
                            bizInNoField.setAccessible(true);

                            Field consumeFeeField = pbCls.getDeclaredField("consumeFee");
                            bizInNoField.setAccessible(true);


                            Field consumeStatusField = pbCls.getDeclaredField("consumeStatus");
                            bizInNoField.setAccessible(true);

                            Field createTimeField = pbCls.getDeclaredField("createTime");
                            createTimeField.setAccessible(true);

                            Field bizSubTypeField = pbCls.getDeclaredField("bizSubType");
                            bizSubTypeField.setAccessible(true);

                            Field categoryNameField = pbCls.getDeclaredField("categoryName");
                            categoryNameField.setAccessible(true);

                            Field bizTypeField = pbCls.getDeclaredField("bizType");
                            bizTypeField.setAccessible(true);

                            String bizInNo = (String) bizInNoField.get(res);
                            String consumeFee = (String) consumeFeeField.get(res);
                            String consumeStatus = (String) consumeStatusField.get(res);
                            String createTime = (String) createTimeField.get(res);
                            String categoryName = (String) categoryNameField.get(res);
                            if (!StringUtil.isEmptyStr(bizInNo) && !StringUtil.isEmptyStr(consumeFee) && !StringUtil.isEmptyStr(createTime) && !StringUtil.isEmptyStr(consumeStatus)) {
                                if (STATUS_QRCODE.equals(consumeStatus) && CATEGORY_NAME_SMALL_BUSINESS.equals(categoryName)) {
                                    LogUtil.log("ServerQueryRunnable bizInNo = " + bizInNo);
                                    String time = StringUtil.getTime(bizInNo, createTime);
                                    AliPayOrderList list = new AliPayOrderList();
                                    list.setBizInNo(bizInNo);
                                    list.setTime(time);
                                    list.setConsumeFee(consumeFee);
                                    mAliPayServerCheckOrderList.add(list);
                                }
                            }
                        }
                    }
                    Field hasMoreField = queryListResCls.getDeclaredField("hasMore");
                    hasMoreField.setAccessible(true);
                    boolean hasMore = (boolean) hasMoreField.get(result);
                    LogUtil.log("hasMore = " + hasMore);
                    while (true && hasMore) {
                        Field pagingField = queryListResCls.getDeclaredField("paging");
                        pagingField.setAccessible(true);
                        Object nextPaging = pagingField.get(result);
                        LogUtil.log("nextPaging " + nextPaging.toString());
                        Object objectNext = cls.newInstance();
                        bizSubTypeReqField.set(objectNext, BIZ_SUB_TYPE_SMALL_BUSINESS);
                        endTime.set(objectNext, mEndTime);
                        startTime.set(objectNext, mStartTime);
                        scene.set(objectNext, "BILL_LIST");
                        needMonthSeparator.set(objectNext, false);
                        asyncQueryTaskId.set(objectNext, 0L);
                        dateType.set(objectNext, mDateType);
                        categoryId.set(objectNext, TYPE_CATEGORYID);
                        paging.set(objectNext, nextPaging);

                        Object objectNextRunnable = runnableCls.newInstance();
                        Object resultNext = method.invoke(objectNextRunnable, new Object[]{new Object[]{objectNext}});
                        queryListRes = (List) billListItemsField.get(resultNext);
                        size = queryListRes.size();
                        LogUtil.log("ServerQueryRunnable2 size = " + size);
                        if (size != 0) {
                            for (int i = 0; i < size; i++) {
                                Object res = queryListRes.get(i);

                                Field bizInNoField = pbCls.getDeclaredField("bizInNo");
                                bizInNoField.setAccessible(true);

                                Field consumeFeeField = pbCls.getDeclaredField("consumeFee");
                                bizInNoField.setAccessible(true);

                                Field consumeStatusField = pbCls.getDeclaredField("consumeStatus");
                                bizInNoField.setAccessible(true);

                                Field createTimeField = pbCls.getDeclaredField("createTime");
                                createTimeField.setAccessible(true);

                                Field bizSubTypeField = pbCls.getDeclaredField("bizSubType");
                                bizSubTypeField.setAccessible(true);

                                Field categoryNameField = pbCls.getDeclaredField("categoryName");
                                categoryNameField.setAccessible(true);

                                Field bizTypeField = pbCls.getDeclaredField("bizType");
                                bizTypeField.setAccessible(true);

                                String bizInNo = (String) bizInNoField.get(res);
                                String consumeFee = (String) consumeFeeField.get(res);
                                String consumeStatus = (String) consumeStatusField.get(res);
                                String createTime = (String) createTimeField.get(res);
                                String categoryName = (String) categoryNameField.get(res);

                                if (!StringUtil.isEmptyStr(bizInNo) && !StringUtil.isEmptyStr(consumeFee) && !StringUtil.isEmptyStr(createTime) && !StringUtil.isEmptyStr(consumeStatus)) {
                                    if (STATUS_QRCODE.equals(consumeStatus) && CATEGORY_NAME_SMALL_BUSINESS.equals(categoryName)) {
                                        LogUtil.log("ServerQueryRunnable2 bizInNo = " + bizInNo);
                                        String time = StringUtil.getTime(bizInNo, createTime);
                                        AliPayOrderList list = new AliPayOrderList();
                                        list.setBizInNo(bizInNo);
                                        list.setTime(time);
                                        list.setConsumeFee(consumeFee);
                                        mAliPayServerCheckOrderList.add(list);
                                    }
                                }
                            }
                        }
                        hasMore = (boolean) hasMoreField.get(resultNext);
                        result = resultNext;
                    }
                    if (mAliPayServerCheckOrderList.size() > 0) {
                        boolean canDeal = true;
                        if (mQueryType == TYPE_SERVER_QUERY_ORDER) {
                            boolean exist = false;
                            for (AliPayOrderList list : mAliPayServerCheckOrderList) {
                                String bizNo = list.getBizInNo();
                                if (bizNo.equals(mOrder)) {
                                    exist = true;
                                    break;
                                }
                            }
                            if (!exist) {
                                LogUtil.log("ServerQueryRunnable TYPE_SERVER_QUERY_ORDER not exist");
                                mAliPayServerCheckOrderList.clear();
                                deleteTaskDatabase();
                                checkTask();
                                canDeal = false;
                            }
                        }
                        if (canDeal) {
                            AliPayQueryModel model = new AliPayQueryModel();
                            model.setStartTime(mStartTime);
                            model.setEndTime(mEndTime);
                            wrapperSimulateStartMsg(model);
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    LogUtil.log("ClassNotFoundException reason " + e.getMessage());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    LogUtil.log("IllegalAccessException reason " + e.getMessage());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                    LogUtil.log("InstantiationException reason " + e.getMessage());
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                    LogUtil.log("NoSuchFieldException reason " + e.getMessage());
                } catch (NoSuchMethodException e) {
                    LogUtil.log("NoSuchMethodException reason " + e.getMessage());
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    LogUtil.log("InvocationTargetException reason " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }

    //查询Ali订单列表
    class QueryRunnable implements Runnable {
        long mStartTime;
        long mEndTime;
        String mDateType;

        public void setQueryCondition(long startTime, long endTime, String dateType) {
            mStartTime = startTime;
            mEndTime = endTime;
            mDateType = dateType;
        }

        @Override
        public void run() {
            if (null != mAliPatchClassloader) {
                ++mOrderStatus;
                LogUtil.log("QueryRunnable run mOrderStatus = " + mOrderStatus);
                if (1 == mOrderStatus) {
                    try {
                        LogUtil.log("startTime " + mStartTime);
                        LogUtil.log("endTime " + mEndTime);
                        Class<?> cls = mClassLoader.loadClass(CLASS_QUERY_LIST_REQ);
                        Object object = cls.newInstance();
                        Field category = cls.getDeclaredField("category");
                        category.setAccessible(true);
                        category.set(object, "ALL");
                        Field pageType = cls.getDeclaredField("pageType");
                        pageType.setAccessible(true);
                        pageType.set(object, "WaitPayConsumeQuery");
                        Field paging = cls.getDeclaredField("paging");
                        paging.setAccessible(true);
                        Class<?> pageConditionCls = mClassLoader.loadClass(CLASS_PAGING_CONDITION);
                        Object objectPageCondition = pageConditionCls.newInstance();
                        paging.set(object, objectPageCondition);
                        Field needMonthSeparator = cls.getDeclaredField("needMonthSeparator");
                        needMonthSeparator.setAccessible(true);
                        needMonthSeparator.set(object, false);

                        Field scene = cls.getDeclaredField("scene");
                        scene.setAccessible(true);
                        scene.set(object, "BILL_LIST");

                        Field startTime = cls.getDeclaredField("startTime");
                        startTime.setAccessible(true);
                        startTime.set(object, mStartTime);

                        Field endTime = cls.getDeclaredField("endTime");
                        endTime.setAccessible(true);
                        endTime.set(object, mEndTime);

                        Field asyncQueryTaskId = cls.getDeclaredField("asyncQueryTaskId");
                        asyncQueryTaskId.setAccessible(true);
                        asyncQueryTaskId.set(object, 0L);

                        Field dateType = cls.getDeclaredField("dateType");
                        dateType.setAccessible(true);
                        dateType.set(object, mDateType);

                        Field categoryId = cls.getDeclaredField("categoryId");
                        categoryId.setAccessible(true);
                        categoryId.set(object, TYPE_CATEGORYID);

                        Field bizSubTypeReqField = cls.getDeclaredField("bizSubType");
                        bizSubTypeReqField.setAccessible(true);
                        bizSubTypeReqField.set(object, BIZ_SUB_TYPE_SMALL_BUSINESS);


                        Class<?> runnableCls = mAliPatchClassloader.loadClass(CLASS_GET_BILL_LIST_DATA_RUNNABLE);
                        Object objectRunnable = runnableCls.newInstance();
                        Method method = runnableCls.getDeclaredMethod("execute", Object[].class);
                        method.setAccessible(true);
                        Object result = method.invoke(objectRunnable, new Object[]{new Object[]{object}});
                        Class queryListResCls = mClassLoader.loadClass(CLASS_QUERY_LIST_RES);
                        Field billListItemsField = queryListResCls.getDeclaredField("billListItems");
                        billListItemsField.setAccessible(true);
                        List queryListRes = (List) billListItemsField.get(result);
                        Class<?> pbCls = mClassLoader.loadClass(CLASS_SINGLE_LIST_ITEM);

                        int size = queryListRes.size();
                        LogUtil.log("QueryRunnable size = " + size);
                        if (size != 0) {
                            for (int i = 0; i < size; i++) {
                                Object res = queryListRes.get(i);

                                Field bizInNoField = pbCls.getDeclaredField("bizInNo");
                                bizInNoField.setAccessible(true);

                                Field consumeFeeField = pbCls.getDeclaredField("consumeFee");
                                bizInNoField.setAccessible(true);


                                Field consumeStatusField = pbCls.getDeclaredField("consumeStatus");
                                bizInNoField.setAccessible(true);

                                Field createTimeField = pbCls.getDeclaredField("createTime");
                                createTimeField.setAccessible(true);

                                Field bizSubTypeField = pbCls.getDeclaredField("bizSubType");
                                bizSubTypeField.setAccessible(true);

                                Field categoryNameField = pbCls.getDeclaredField("categoryName");
                                categoryNameField.setAccessible(true);

                                Field bizTypeField = pbCls.getDeclaredField("bizType");
                                bizTypeField.setAccessible(true);

                                String bizInNo = (String) bizInNoField.get(res);
                                String consumeFee = (String) consumeFeeField.get(res);
                                String consumeStatus = (String) consumeStatusField.get(res);
                                String createTime = (String) createTimeField.get(res);
                                String categoryName = (String) categoryNameField.get(res);
                                if (!StringUtil.isEmptyStr(bizInNo) && !StringUtil.isEmptyStr(consumeFee) && !StringUtil.isEmptyStr(createTime) && !StringUtil.isEmptyStr(consumeStatus)) {
                                    if (STATUS_QRCODE.equals(consumeStatus) && CATEGORY_NAME_SMALL_BUSINESS.equals(categoryName)) {
                                        LogUtil.log("QueryRunnable bizInNo " + bizInNo);
                                        String time = StringUtil.getTime(bizInNo, createTime);
                                        AliPayOrderList list = new AliPayOrderList();
                                        list.setBizInNo(bizInNo);
                                        list.setTime(time);
                                        list.setConsumeFee(consumeFee);
                                        if (0 != mAliPayAllOrderList.size()) {
                                            if (!mAliPayAllOrderList.contains(list)) {
                                                mAliPayOnceOrderList.add(list);
                                            }

                                        } else {
                                            mAliPayOnceOrderList.add(list);
                                        }
                                    }
                                }
                            }
                            Field hasMoreField = queryListResCls.getDeclaredField("hasMore");
                            hasMoreField.setAccessible(true);
                            boolean hasMore = (boolean) hasMoreField.get(result);
                            while (true && hasMore) {
                                Field pagingField = queryListResCls.getDeclaredField("paging");
                                pagingField.setAccessible(true);
                                Object nextPaging = pagingField.get(result);
                                LogUtil.log("nextPaging " + nextPaging.toString());
                                Object objectNext = cls.newInstance();
                                bizSubTypeReqField.set(objectNext, BIZ_SUB_TYPE_SMALL_BUSINESS);
                                endTime.set(objectNext, mEndTime);
                                startTime.set(objectNext, mStartTime);
                                scene.set(objectNext, "BILL_LIST");
                                needMonthSeparator.set(objectNext, false);
                                asyncQueryTaskId.set(objectNext, 0L);
                                dateType.set(objectNext, mDateType);
                                categoryId.set(objectNext, TYPE_CATEGORYID);
                                paging.set(objectNext, nextPaging);

                                Object objectNextRunnable = runnableCls.newInstance();
                                Object resultNext = method.invoke(objectNextRunnable, new Object[]{new Object[]{objectNext}});
                                queryListRes = (List) billListItemsField.get(resultNext);
                                size = queryListRes.size();
                                LogUtil.log("ServerQueryRunnable2 size = " + size);
                                if (size != 0) {
                                    for (int i = 0; i < size; i++) {
                                        Object res = queryListRes.get(i);

                                        Field bizInNoField = pbCls.getDeclaredField("bizInNo");
                                        bizInNoField.setAccessible(true);

                                        Field consumeFeeField = pbCls.getDeclaredField("consumeFee");
                                        bizInNoField.setAccessible(true);

                                        Field consumeStatusField = pbCls.getDeclaredField("consumeStatus");
                                        bizInNoField.setAccessible(true);

                                        Field createTimeField = pbCls.getDeclaredField("createTime");
                                        createTimeField.setAccessible(true);

                                        Field bizSubTypeField = pbCls.getDeclaredField("bizSubType");
                                        bizSubTypeField.setAccessible(true);

                                        Field categoryNameField = pbCls.getDeclaredField("categoryName");
                                        categoryNameField.setAccessible(true);

                                        Field bizTypeField = pbCls.getDeclaredField("bizType");
                                        bizTypeField.setAccessible(true);

                                        String bizInNo = (String) bizInNoField.get(res);
                                        String consumeFee = (String) consumeFeeField.get(res);
                                        String consumeStatus = (String) consumeStatusField.get(res);
                                        String createTime = (String) createTimeField.get(res);
                                        if (!StringUtil.isEmptyStr(bizInNo) && !StringUtil.isEmptyStr(consumeFee) && !StringUtil.isEmptyStr(createTime) && !StringUtil.isEmptyStr(consumeStatus)) {
                                            if (STATUS_QRCODE.equals(consumeStatus)) {
                                                LogUtil.log("QueryRunnable2 bizInNo " + bizInNo);
                                                String time = StringUtil.getTime(bizInNo, createTime);
                                                AliPayOrderList list = new AliPayOrderList();
                                                list.setBizInNo(bizInNo);
                                                list.setTime(time);
                                                list.setConsumeFee(consumeFee);
                                                if (0 != mAliPayAllOrderList.size()) {
                                                    if (!mAliPayAllOrderList.contains(list)) {
                                                        mAliPayOnceOrderList.add(list);
                                                    }

                                                } else {
                                                    mAliPayOnceOrderList.add(list);
                                                }
                                            }
                                        }
                                    }
                                }
                                hasMore = (boolean) hasMoreField.get(resultNext);
                                result = resultNext;
                                LogUtil.log("ServerQueryRunnable2 hasMore = " + hasMore);
                            }
                            if (0 != mAliPayOnceOrderList.size()) {
                                Collections.sort(mAliPayOnceOrderList);
                                mAliPayAllOrderList.addAll(mAliPayOnceOrderList);
                                Collections.sort(mAliPayAllOrderList);
                                mHandler.sendEmptyMessage(MSG_TYPE_SIMULATE_CLICK_START);
                                printAllOrder();
                                printOnceOrder();
                            } else {
                                LogUtil.log("MSG_TYPE_START_DOT mQueryType " + mQueryType);
                                mQuery = false;
                                if (mQueryType == TYPE_AUTO_QUERY) {
                                    mHandler.sendEmptyMessage(MSG_TYPE_START_DOT);
                                }
                                mOrderStatus = 0;
                            }
                        } else {
                            mQuery = false;
                            if (mQueryType == TYPE_AUTO_QUERY) {
                                mHandler.sendEmptyMessage(MSG_TYPE_START_DOT);
                            }
                            mOrderStatus = 0;
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        LogUtil.log("ClassNotFoundException reason " + e.getMessage());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        LogUtil.log("IllegalAccessException reason " + e.getMessage());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                        LogUtil.log("InstantiationException reason " + e.getMessage());
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                        LogUtil.log("NoSuchFieldException reason " + e.getMessage());
                    } catch (NoSuchMethodException e) {
                        LogUtil.log("NoSuchMethodException reason " + e.getMessage());
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        LogUtil.log("InvocationTargetException reason " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    // server check detail
    class AliPayServerJavaScriptInterface implements ValueCallback<String> {
        @Override
        public void onReceiveValue(String s) {
            parseHtmlContent(s);
        }

        private void parseHtmlContent(String str) {
            str = str.trim();
            // remove "
            str = str.replaceAll("\"", "");
            int index = 0;
            int maxLen = 2000;
            int size = str.length();
            for (; index < size - maxLen; index = index + maxLen) {
                LogUtil.log(str.substring(index, index + maxLen));
            }
            LogUtil.log(str.substring(index, size));
            if (!TextUtils.isEmpty(str)) {
                LogUtil.log("str = " + str);
                String[] details = str.split("\\|\\|");
                int len = details.length;
                LogUtil.log("len = " + len);
                //6 商户版 ，5 普通版
                if (len == 6 || len == 5) {
                    String money = details[0];
                    String remark = details[1];
                    //skip details[2]
                    String time = details[3];
                    String binInNo = details[4];
                    String formatTime = StringUtil.getTime(time);
                    LogUtil.log("AliPayServerJavaScriptInterface binInNo = " + binInNo + " remark = " + remark);
                    String date = StringUtil.getDate(binInNo);
                    int listSize = mAliPayServerCheckOrderList.size();
                    int queryType = mServerOrderRunnable.getQueryType();
                    LogUtil.log("listSize " + listSize + " queryType = " + queryType);
                    if (0 != listSize) {
                        if (TYPE_SERVER_QUERY_TIME_ONLY == queryType) {
                            String lastBizInNo = mAliPayServerCheckOrderList.get(listSize - 1).getBizInNo();
                            boolean find = false;
                            boolean findLast = false;
                            for (AliPayOrderList list : mAliPayServerCheckOrderList) {
                                String biz = list.getBizInNo();
                                LogUtil.log("AliPayServerJavaScriptInterface biz = " + biz);
                                if (list.getBizInNo().equals(binInNo)) {
                                    ContentValues contentValues = new ContentValues();
                                    contentValues.put(AliPayColumn._MONEY, money);
                                    contentValues.put(AliPayColumn._TIME_STAMP, formatTime);
                                    contentValues.put(AliPayColumn._ORDER_NUMBER, binInNo);
                                    contentValues.put(AliPayColumn._REMARK, remark);
                                    contentValues.put(AliPayColumn._DATE, date);
                                    contentValues.put(AliPayColumn._ACCOUNT, mAliAccount);
                                    mContentResolver.insert(mTempUri, contentValues);
                                    if (binInNo.equals(lastBizInNo)) {
                                        findLast = true;
                                        deleteTaskDatabase();
                                        wrapperSimulateStopMsg();
                                    } else {
                                        wrapperSimulateContinueMsg();
                                        find = true;
                                    }
                                    break;
                                }
                            }
                            //如果找不到的话并且不是最后一条的话,继续查询
                            if (!find && !findLast) {
                                wrapperSimulateContinueMsg();
                            }
                        } else if (TYPE_SERVER_QUERY_REMARK == queryType) {
                            String reason = mServerOrderRunnable.getRemark();
                            LogUtil.log("AliPayServerJavaScriptInterface reason = " + reason + " remark = " + remark);
                            if (reason.equals(remark)) {
                                deleteTaskDatabase();
                                wrapperSimulateStopMsg();
                            } else {
                                wrapperSimulateContinueMsg();
                            }
                        } else if (TYPE_SERVER_QUERY_ORDER == queryType) {
                            String order = mServerOrderRunnable.getOrder();
                            LogUtil.log("AliPayServerJavaScriptInterface order = " + order + " binInNo = " + binInNo);
                            if (mServerOrderRunnable.getOrder().equals(binInNo)) {
                                deleteTaskDatabase();
                                wrapperSimulateStopMsg();
                            } else {
                                wrapperSimulateContinueMsg();
                            }
                        }
                    }
                } else {
                    LogUtil.log("MSG_TYPE_GET_DETAIL_FAIL1 = " + MSG_TYPE_GET_DETAIL_FAIL);
                    //也许找不到内容
                    mHandler.sendEmptyMessage(MSG_TYPE_GET_DETAIL_FAIL);
                }
            } else {
                LogUtil.log("MSG_TYPE_GET_DETAIL_FAIL2 = " + MSG_TYPE_GET_DETAIL_FAIL);
                mHandler.sendEmptyMessage(MSG_TYPE_GET_DETAIL_FAIL);
            }
        }
    }

    //订单详情结果处理
    class AliPayJavaScriptInterface implements ValueCallback<String> {
        @Override
        public void onReceiveValue(String s) {
            parseHtmlContent(s);
        }

        private void parseHtmlContent(String str) {
            str = str.trim();
            // remove "
            str = str.replaceAll("\"", "");
            int index = 0;
            int maxLen = 2000;
            int size = str.length();
            for (; index < size - maxLen; index = index + maxLen) {
                LogUtil.log(str.substring(index, index + maxLen));
            }
            LogUtil.log(str.substring(index, size));
            if (!TextUtils.isEmpty(str)) {
                LogUtil.log("str = " + str);
                String[] details = str.split("\\|\\|");
                int len = details.length;
                LogUtil.log("len = " + len);
                //6 商户版 ，5 普通版
                if (len == 6 || len == 5) {
                    String money = details[0];
                    String remark = details[1];
                    //skip details[2]
                    String time = details[3];
                    String binInNo = details[4];
                    String formatTime = StringUtil.getTime(time);
                    LogUtil.log(String.format("time = %s, money = %s,binInNo = %s,formatTime = %s,remark = %s", time, money, binInNo, formatTime, remark));
                    String date = StringUtil.getDate(binInNo);
                    int listSize = mAliPayOnceOrderList.size();
                    ContentValues contentValues = new ContentValues();
                    contentValues.put(AliPayColumn._MONEY, money);
                    contentValues.put(AliPayColumn._TIME_STAMP, formatTime);
                    contentValues.put(AliPayColumn._ORDER_NUMBER, binInNo);
                    contentValues.put(AliPayColumn._REMARK, remark);
                    contentValues.put(AliPayColumn._DATE, date);
                    contentValues.put(AliPayColumn._ACCOUNT, mAliAccount);
                    mContentResolver.insert(mUri, contentValues);
                    if (0 != listSize) {
                        LogUtil.log("listSize " + listSize + " mQueryType = " + mQueryType + " mOrderStatus = " + mOrderStatus);
                        printOnceOrder();
                        if (mAliPayOnceOrderList.get(listSize - 1).getBizInNo().equals(binInNo)) {
                            //finish
                            mAliPayOnceOrderList.clear();
                            mHandler.sendEmptyMessage(MSG_TYPE_SIMULATE_CLICK_STOP);
                            mQuery = false;
                            if (mQueryType == TYPE_AUTO_QUERY) {
                                mHandler.sendEmptyMessage(MSG_TYPE_START_DOT);
                            }
                            if (1 != mOrderStatus) {
                                mOrderStatus = 0;
                                queryOrderInner();
                            } else {
                                mOrderStatus = 0;
                            }
                        } else {
                            //continue
                            mHandler.sendEmptyMessage(MSG_TYPE_SIMULATE_CLICK_CONTINUE);
                        }
                    }
                } else {
                    LogUtil.log("MSG_TYPE_GET_DETAIL_FAIL1 = " + MSG_TYPE_GET_DETAIL_FAIL);
                    //也许找不到内容
                    mHandler.sendEmptyMessage(MSG_TYPE_GET_DETAIL_FAIL);
                }
            } else {
                LogUtil.log("MSG_TYPE_GET_DETAIL_FAIL2 = " + MSG_TYPE_GET_DETAIL_FAIL);
                mHandler.sendEmptyMessage(MSG_TYPE_GET_DETAIL_FAIL);
            }
        }
    }

    //清除订单list
    private void clearPayOrderList() {
        if (null != mAliPayAllOrderList) {
            mAliPayAllOrderList.clear();
        }
        if (null != mAliPayOnceOrderList) {
            mAliPayOnceOrderList.clear();
        }
    }

    //设置ali的账号
    private void setAliAccount(String aliAccount) {
        mAliAccount = aliAccount;
    }

    //是否设置ali账号, true 设置了
    private boolean isAliAccountSet() {
        if (!TextUtils.isEmpty(mAliAccount)) {
            return true;
        }
        return false;
    }

    //删除任务数据库已经查询的
    private void deleteTaskDatabase() {
        Cursor cursor = mContentResolver.query(mTaskUri, null, AliQueryOrderColumn._TIME_STAMP_BEGIN + " =? "
                + " and " + AliQueryOrderColumn._TIME_STAMP_END + " =? ", new String[]{String.valueOf(mServerOrderRunnable.getStartTime()), String.valueOf(mServerOrderRunnable.getEndTime())}, null
        );
        try {
            if (null != cursor) {
                cursor.moveToFirst();
                int id = cursor.getInt(cursor.getColumnIndexOrThrow(AliQueryOrderColumn._ID));
                Uri deleteUri = ContentUris.withAppendedId(mTaskUri, id);
                mContentResolver.delete(deleteUri, null, null);
                cursor.close();
            }
        } catch (Exception e) {
            LogUtil.log("deleteTaskDatabase exception " + e.getMessage());
        }
    }
}